Cloudflare D1 schema · Worker API · PDF Report™ generation pipeline · email delivery. Everything the diagnostic suite needs to move from client-side prototypes into production.
All 8 diagnostics (WIA, PBR, ICR, TSR, EPR, ExR, FOR, MAR) are currently client-side prototypes using localStorage for state persistence. Production requires server-side submission, storage, PDF generation, and email delivery — plus admin views for Chekelah's team.
submissionsMaster table for every diagnostic submission across all 8 report types.
CREATE TABLE submissions ( id TEXT PRIMARY KEY, -- UUID v7 diagnostic TEXT NOT NULL, -- WIA | PBR | ICR | TSR | EPR | ExR | FOR | MAR | BOD version TEXT NOT NULL, -- v1 submitted_at INTEGER NOT NULL, -- unix ms applicant_name TEXT, applicant_email TEXT NOT NULL, applicant_phone TEXT, applicant_company TEXT, consent_terms INTEGER NOT NULL, -- 1 = accepted raw_state TEXT NOT NULL, -- JSON of all form answers ip_hash TEXT, -- SHA-256 (privacy-preserving) user_agent TEXT, turnstile_score REAL, utm_source TEXT, utm_campaign TEXT, status TEXT NOT NULL DEFAULT 'submitted' -- submitted | pdf-generated | delivered | reviewed | routed ); CREATE INDEX idx_sub_email ON submissions(applicant_email); CREATE INDEX idx_sub_diagnostic ON submissions(diagnostic, submitted_at DESC); CREATE INDEX idx_sub_status ON submissions(status);
scoresComputed scores for each submission — derived from raw_state at submission time, cached for admin queries.
CREATE TABLE scores ( submission_id TEXT PRIMARY KEY REFERENCES submissions(id), overall_score INTEGER NOT NULL, -- 0-100 tier_band TEXT NOT NULL, -- e.g. "TIER 03 · COORDINATION-READY" tier_verdict TEXT NOT NULL, top_moves TEXT NOT NULL, -- JSON array of 6-12 moves with per-move scores computed_at INTEGER NOT NULL );
routingSpecialist-routing recommendations produced by the diagnostic — used to trigger partner-firm handoffs.
CREATE TABLE routing ( id TEXT PRIMARY KEY, submission_id TEXT NOT NULL REFERENCES submissions(id), specialist_type TEXT NOT NULL, -- CPA | ATTORNEY | LENDER | IB | INSURANCE | RIA discipline TEXT NOT NULL, -- ESTATE, M&A, TAX-PLANNING, SBA, JUMBO, etc. urgency TEXT NOT NULL, -- URGENT | HIGH | STANDARD partner_id TEXT REFERENCES partners(id), -- nullable · matched later status TEXT NOT NULL DEFAULT 'unmatched', -- unmatched | matched | intro-sent | engaged | closed created_at INTEGER NOT NULL );
partnersVetted partner firms (from Partnership Program) — matched to routing entries.
CREATE TABLE partners ( id TEXT PRIMARY KEY, firm_name TEXT NOT NULL, primary_contact TEXT NOT NULL, email TEXT NOT NULL, specialist_type TEXT NOT NULL, disciplines TEXT NOT NULL, -- JSON array geography TEXT NOT NULL, -- e.g. "DFW", "NATIONAL" mou_signed_at INTEGER, status TEXT NOT NULL DEFAULT 'active' -- active | paused | ended );
reportsGenerated PDF reports — R2 object references.
CREATE TABLE reports ( submission_id TEXT PRIMARY KEY REFERENCES submissions(id), r2_key TEXT NOT NULL, -- "reports/{id}.pdf" pdf_size_bytes INTEGER NOT NULL, generated_at INTEGER NOT NULL, delivered_at INTEGER, version TEXT NOT NULL -- template version );
POST /api/submitAccepts a diagnostic form submission from the client. Validates, stores, scores, and queues downstream jobs.
// Request body { "diagnostic": "WIA" | "PBR" | "ICR" | "TSR" | "EPR" | "ExR" | "FOR" | "MAR" | "BOD", "version": "v1", "applicant": { "name": "...", "email": "...", "phone": "...", "company": "..." }, "state": { /* full form state, as stored in localStorage */ }, "turnstile": "...", // Cloudflare Turnstile CAPTCHA token "consent": true } // Response { "ok": true, "submission_id": "uuid-v7", "score": 74, "tier_band": "TIER 03 · COORDINATION-READY", "report_eta": "2025-11-15T10:00:00Z" }
GET /admin/queueAdmin-authenticated endpoint (Cloudflare Access-gated) for Chekelah's team to review incoming submissions.
{
"total_pending_review": 12,
"submissions": [
{
"id": "...",
"diagnostic": "ICR",
"applicant": { "name": "...", "email": "...", "company": "..." },
"score": 74,
"tier_band": "...",
"submitted_at": 1730000000000,
"pdf_url": "https://reports.hlpcredit.com/...",
"routing_recommendations": [ /* array of specialist recs */ ]
}
]
}
POST /admin/route/:submission_idChekelah's team matches routing entries to specific partner firms + sends warm-intro emails.
/admin/* endpoints are gated by Cloudflare Access with Google Workspace SSO limited to @hlpcredit.com domain. No auth token leaks — Cloudflare handles session management.
PDF generation runs as a queued job — decoupled from the submit response to keep the client-side experience snappy.
Every diagnostic has its own PDF template stored in R2. Templates use Handlebars for dynamic score data + move rendering:
templates/ ├── WIA/v1/ │ ├── template.html // Handlebars HTML │ ├── styles.css // Print-optimized CSS │ └── cover.svg ├── PBR/v1/ ├── ICR/v1/ ├── TSR/v1/ ├── EPR/v1/ ├── ExR/v1/ ├── FOR/v1/ ├── MAR/v1/ └── shared/ ├── header.html // HLP logo + report meta ├── footer.html // Compliance disclaimer └── styles-base.css
Every diagnostic promises delivery within 48 hours. Two-stage email flow ensures both machine-speed acknowledgment and human-review completion.
| Stage | Trigger | Template | Contents |
|---|---|---|---|
| 01 · IMMEDIATE | On submission | submission-received | Confirmation · score preview · 48hr Report™ promise |
| 02 · PDF READY | PDF generated (queue) | report-preview | PDF Report™ · signed URL · Chekelah review note |
| 03 · CHEKELAH | Manual · Chekelah | personal-followup | Personal note · specialist introductions · book-a-call CTA |
Email is sent via Cloudflare Email Routing for inbound and Resend for outbound transactional. MJML templates render to responsive HTML.
| Control | Implementation |
|---|---|
| PII AT REST | D1 stores raw form state · Cloudflare-native encryption at rest |
| PII IN TRANSIT | TLS 1.3 everywhere · HSTS · CSP headers on client |
| IP HASHING | Client IP SHA-256 hashed before storage · never raw |
| DATA RETENTION | Submissions purged after 24 months · reports after 12 months |
| ACCESS CONTROL | Cloudflare Access · SSO-gated · @hlpcredit.com domain only |
| AUDIT LOG | All admin actions written to append-only D1 audit_log table |
| DATA EXPORT | Clients can request full data export via GLBA/CCPA endpoint |
| DATA DELETION | 60-day full-deletion SLA on client request |
| THIRD-PARTY | Zero third-party analytics · zero ad trackers · zero session replay |
Following the existing HLP subdomain architecture:
| Component | Cloudflare Product | URL |
|---|---|---|
| Client (static) | Pages | capital.hlpcredit.com |
| API Worker | Workers | api.hlpcredit.com |
| Database | D1 | hlp-capital-advisory (binding) |
| Object storage | R2 | hlp-reports (bucket) |
| Queue | Cloudflare Queues | hlp-pdf, hlp-email |
| Admin console | Pages + Access | admin.hlpcredit.com |
| PDF viewer | Pages · signed URL | reports.hlpcredit.com |
Recommended 4-phase implementation:
/api/submit · basic PDF generation (single template) · admin queue view